#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdbool.h>
#include "log.h"

// 全局变量
static bool g_is_initialized = false;
static log_config_t g_log_config;
static FILE *g_log_file = NULL;
static pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
static char g_log_file_path[256] = {0};

// 获取日志级别名称
static const char *log_level_name(enum log_level level)
{
    switch (level) {
        case LOG_LEVEL_DEBUG:
            return "DEBUG";
        case LOG_LEVEL_INFO:
            return "INFO";
        case LOG_LEVEL_WARN:
            return "WARN";
        case LOG_LEVEL_ERROR:
            return "ERROR";
        case LOG_LEVEL_FATAL:
            return "FATAL";
        default:
            return "UNKNOWN";
    }
}

// 检查日志文件大小并滚动
static void check_log_rollover(void)
{
    if (!g_log_config.file_output || !g_log_file_path[0]) {
        return;
    }
    
    struct stat file_stat;
    if (stat(g_log_file_path, &file_stat) != 0) {
        return;
    }
    
    // 检查文件大小是否超过限制（转换为KB）
    if ((file_stat.st_size / 1024) >= g_log_config.max_file_size) {
        // 关闭当前日志文件
        if (g_log_file) {
            fclose(g_log_file);
            g_log_file = NULL;
        }
        
        // 滚动日志文件
        char old_log_path[256];
        
        // 删除最旧的日志文件
        for (int i = g_log_config.max_files - 1; i >= 1; i--) {
            // 确保缓冲区足够大，避免截断警告
            int old_path_len = snprintf(old_log_path, sizeof(old_log_path), "%s.%d", g_log_file_path, i - 1);
            char new_log_path[256];
            int new_path_len = snprintf(new_log_path, sizeof(new_log_path), "%s.%d", g_log_file_path, i);
            
            // 检查是否有截断发生
            if ((size_t)old_path_len < sizeof(old_log_path) && (size_t)new_path_len < sizeof(new_log_path)) {
                rename(old_log_path, new_log_path);
            }
        }
        
        // 将当前日志文件重命名为.1
        int old_path_len = snprintf(old_log_path, sizeof(old_log_path), "%s.1", g_log_file_path);
        
        // 检查是否有截断发生
        if ((size_t)old_path_len < sizeof(old_log_path)) {
            rename(g_log_file_path, old_log_path);
        }
        
        // 打开新的日志文件
        g_log_file = fopen(g_log_file_path, "a");
    }
}

void log_init(void)
{
    pthread_mutex_lock(&g_log_mutex);
    
    if (g_is_initialized) {
        pthread_mutex_unlock(&g_log_mutex);
        return;
    }
    
    // 初始化默认配置
    g_log_config.level = LOG_LEVEL_INFO;
    g_log_config.log_file = "/tmp/drone_demo.log";
    g_log_config.console_output = true;
    g_log_config.file_output = true;
    g_log_config.max_file_size = 1024; // 1MB
    g_log_config.max_files = 5;
    
    // 复制日志文件路径
    strncpy(g_log_file_path, g_log_config.log_file, sizeof(g_log_file_path) - 1);
    
    // 打开日志文件
    if (g_log_config.file_output) {
        g_log_file = fopen(g_log_file_path, "a");
        if (!g_log_file) {
            fprintf(stderr, "无法打开日志文件: %s, 错误: %s\n", 
                    g_log_file_path, strerror(errno));
            g_log_config.file_output = false;
        }
    }
    
    g_is_initialized = true;
    pthread_mutex_unlock(&g_log_mutex);
    
    // 使用临时方式输出日志，避免循环依赖
    fprintf(stderr, "[日志系统初始化成功]\n");
}

void log_cleanup(void)
{
    pthread_mutex_lock(&g_log_mutex);
    
    if (!g_is_initialized) {
        pthread_mutex_unlock(&g_log_mutex);
        return;
    }
    
    // 关闭日志文件
    if (g_log_file) {
        fclose(g_log_file);
        g_log_file = NULL;
    }
    
    g_is_initialized = false;
    pthread_mutex_unlock(&g_log_mutex);
}

void log_set_config(log_config_t *config)
{
    if (!config) {
        return;
    }
    
    pthread_mutex_lock(&g_log_mutex);
    
    // 更新配置
    g_log_config = *config;
    
    // 如果更改了日志文件路径，重新打开文件
    if (strcmp(g_log_file_path, g_log_config.log_file) != 0) {
        // 关闭旧文件
        if (g_log_file) {
            fclose(g_log_file);
            g_log_file = NULL;
        }
        
        // 复制新路径
        strncpy(g_log_file_path, g_log_config.log_file, sizeof(g_log_file_path) - 1);
        
        // 打开新文件
        if (g_log_config.file_output) {
            g_log_file = fopen(g_log_file_path, "a");
            if (!g_log_file) {
                fprintf(stderr, "无法打开日志文件: %s, 错误: %s\n", 
                        g_log_file_path, strerror(errno));
                g_log_config.file_output = false;
            }
        }
    }
    
    pthread_mutex_unlock(&g_log_mutex);
}

void log_set_level(enum log_level level)
{
    pthread_mutex_lock(&g_log_mutex);
    g_log_config.level = level;
    pthread_mutex_unlock(&g_log_mutex);
}

void log_output(enum log_level level, const char *file, int line, const char *func, 
               const char *format, va_list args)
{
    pthread_mutex_lock(&g_log_mutex);
    
    if (!g_is_initialized) {
        pthread_mutex_unlock(&g_log_mutex);
        return;
    }
    
    // 检查日志级别
    if (level < g_log_config.level) {
        pthread_mutex_unlock(&g_log_mutex);
        return;
    }
    
    // 获取当前时间
    time_t now = time(NULL);
    struct tm *tm_info = localtime(&now);
    char time_str[64];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);
    
    // 格式化日志前缀
    char log_prefix[128];
    snprintf(log_prefix, sizeof(log_prefix), "[%s] [%s] %s:%d %s() ", 
             time_str, log_level_name(level), file, line, func);
    
    // 输出到控制台
    if (g_log_config.console_output) {
        fprintf(stderr, "%s", log_prefix);
        vfprintf(stderr, format, args);
        fprintf(stderr, "\n");
        fflush(stderr);
    }
    
    // 输出到文件
    if (g_log_config.file_output && g_log_file) {
        // 检查是否需要滚动日志
        check_log_rollover();
        
        fprintf(g_log_file, "%s", log_prefix);
        vfprintf(g_log_file, format, args);
        fprintf(g_log_file, "\n");
        fflush(g_log_file);
    }
    
    pthread_mutex_unlock(&g_log_mutex);
}

// 日志包装函数实现
void log_debug(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    log_output(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __func__, format, args);
    va_end(args);
}

void log_info(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    log_output(LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, format, args);
    va_end(args);
}

void log_warn(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    log_output(LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, format, args);
    va_end(args);
}

void log_error(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    log_output(LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, format, args);
    va_end(args);
}

void log_fatal(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    log_output(LOG_LEVEL_FATAL, __FILE__, __LINE__, __func__, format, args);
    va_end(args);
}